# coding=utf-8
from playwright.sync_api import sync_playwright
import time
import json
from parsel import Selector
import cv2
import base64
import re
import os
import random
from retrying import retry

inst_code_dict = {'XHHG': (r'42264', r'Xhhg2019@'), 'XH': (
    '12420000420007938Y', 'Whxh@85755457'), 'WB': ('13283766953', 'Ws123456+++')}


def targetx(bg_path, tp_path):
    # bg_path为背景图片，tp_path为滑块图片
    bg_img = cv2.imread(bg_path)
    tp_img = cv2.imread(tp_path)
    # 识别图片边缘
    bg_edge = cv2.Canny(bg_img, 100, 200)
    tp_edge = cv2.Canny(tp_img, 100, 200)
    # 转换图片格式
    bg_pic = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB)
    tp_pic = cv2.cvtColor(tp_edge, cv2.COLOR_GRAY2RGB)
    res = cv2.matchTemplate(bg_pic, tp_pic, cv2.TM_CCOEFF_NORMED)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)  # 寻找最优匹配
    # th, tw = tp_pic.shape[:2]
    # tl = max_loc  # 左上角点的坐标
    # br = (tl[0] + tw, tl[1] + th)  # 右下角点的坐标
    x_target = max_loc[0] * 1.29  # 下载的图片比网页显示图片尺寸小，因而真实的缺口位置要做放大
    # print('x_target=' + str(x_target))
    return x_target


def download_img(src, img_path, img_name):
    # 下载图片
    result = re.search(
        "data:image/(?P<ext>.*?);base64,(?P<data>.*)", src, re.DOTALL)
    if result:
        ext = result.groupdict().get('ext')
        data = result.groupdict().get('data')
    else:
        raise Exception("Do not parse!")
    # base64编码
    img = base64.urlsafe_b64decode(data)
    file_path = os.path.join(img_path, f"{img_name}.{ext}")
    with open(file_path, "wb") as f:
        f.write(img)
    return (file_path)


def get_track(distance):  # distance为传入的总距离
    track = []
    current = 0
    mid = distance * 3 / 5
    t = 0.2
    v = 1
    while current < distance:
        if current < mid:
            a = 6
        else:
            a = -2
        v0 = v
        v = v0 + a * t
        move = v0 * t + 1 / 2 * a * t * t
        current += move
        track.append(round(move))
    return track


def huadonyanzhen(page, inst):
    user, passwd = inst_code_dict.get(inst)  # 获取账号密码
    page.goto("https://tysf.cponline.cnipa.gov.cn/am/#/user/login")
    page.wait_for_load_state()
    if inst == 'XHHG':
        page.click('xpath=//span[text()="代理机构登录"]')
        page.wait_for_timeout(1000)
        page.click('xpath=//input[@placeholder="代理机构代码"]')
        page.wait_for_timeout(500)
        page.fill('xpath=//input[@placeholder="代理机构代码"]', user)
        page.wait_for_timeout(1000)
    elif inst == 'XH':
        page.click('xpath=//span[text()="法人登录"]')
        page.wait_for_timeout(1000)
        page.click('xpath=//input[@placeholder="统一社会信用代码"]')
        page.wait_for_timeout(500)
        page.fill('xpath=//input[@placeholder="统一社会信用代码"]', user)
        page.wait_for_timeout(1000)
    elif inst == 'WB':
        page.click('xpath=//span[text()="自然人登录"]')
        page.wait_for_timeout(1000)
        page.click('xpath=//input[@placeholder="手机号/证件号码"]')
        page.wait_for_timeout(500)
        page.fill('xpath=//input[@placeholder="手机号/证件号码"]', user)
        page.wait_for_timeout(1000)
    page.click('xpath=//input[@placeholder="请输入密码"]')
    page.wait_for_timeout(500)
    page.fill('xpath=//input[@placeholder="请输入密码"]', passwd)
    page.wait_for_timeout(500)
    page.click('xpath=//span[text()="登录"]')
    page.wait_for_timeout(10000)
    is_fail = True
    try_num = 1
    while is_fail:
        # 滑动验证码
        login_soup = Selector(page.content())
        bg_src = login_soup.xpath(
            '//div[@class="verify-img-panel"]/img/@src').extract_first()

        tp_src = login_soup.xpath(
            '//div[@class="verify-sub-block"]/img/@src').extract_first()
        if bg_src:
            print(f'---开始第{try_num}次滑动---')
            img_path = os.path.abspath('.')
            bg_path = download_img(
                bg_src, img_path=img_path, img_name=f'bg').replace("\\", "/")
            # page.locator().screenshot(path=)
            tp_path = download_img(
                tp_src, img_path=img_path, img_name=f'tp').replace("\\", "/")
            element = page.query_selector(
                'xpath=//div[@class="verify-move-block"]')  # xpath 滑块小元素
            box = element.bounding_box()
            page.wait_for_timeout(2000)
            x = int(box["x"] + box["width"] / 2)
            y = int(box["y"] + box["height"] / 2)
            page.mouse.move(x + random.randint(-1, 1), y + random.randint(-1, 1))  # 小滑动拖动的滑块中心位置
            page.wait_for_timeout(500)
            page.mouse.down()
            page.wait_for_timeout(500)
            x_target = targetx(bg_path, tp_path)
            print("===================================================bg_path", bg_path)
            print("===================================================tp_path", tp_path)
            time.sleep(10)
            max_x = x_target + box["x"] + box["width"] / 2
            distance = x_target  # 行进的路径
            track_list = get_track(distance)
            i = 0
            x_set = []
            for track in track_list:
                x += track
                x_set.append(x)
            x_set[-1] = max_x
            x_set = sorted(x_set)
            for x_move in x_set:
                page.mouse.move(x_move, y + random.randint(-2, 2), steps=1)
                if i < 0.8 * track_list.__len__():
                    page.wait_for_timeout(random.randint(50, 80))
                else:
                    page.wait_for_timeout(random.randint(150, 200))
                i = i + 1
            page.wait_for_timeout(500)
            page.mouse.up()
            page.wait_for_timeout(3000)
            try_num += 1
            print('------' * 10)
        else:
            print(f'---滑动验证成功---')
            is_fail = False
    page.wait_for_timeout(3000)


@retry(stop_max_attempt_number=3)
def update_auth(inst):
    with sync_playwright() as p:
        browser = p.firefox.launch(headless=False)
        # browser = p.firefox.launch()
        context = browser.new_context(
            base_url='https://cpquery.cponline.cnipa.gov.cn', ignore_https_errors=True)
        context.set_default_timeout(300000)
        context.set_default_navigation_timeout(300000)
        page = context.new_page()
        page.set_default_timeout(300000)
        page.set_default_navigation_timeout(300000)
        huadonyanzhen(page, inst)
        page.wait_for_timeout(3000)
        page.goto(
            r"https://cpquery.cponline.cnipa.gov.cn/chinesepatent/index")
        page.wait_for_load_state()
        page.wait_for_timeout(10000)
        reload_s = True
        while reload_s:
            if '502 Bad Gateway' in page.content():
                page.reload()
                page.wait_for_load_state()
            else:
                reload_s = False
        el = page.locator('xpath=//span[@class="block" and text()="查询"]')
        el.wait_for(timeout=0)
        page.wait_for_timeout(3000)
        if '关于中国及多国专利审查信息查询系统新旧系统双运行模式的通知' in page.content():
            page.click(
                'xpath=//span[@class="q-btn__content text-center col items-center q-anchor--skip justify-end row"]')
        storage = context.storage_state(path=f'./auth/{inst}_state.json')
        print(f'@@{inst}_账号登录信息保存到本地@@')


if __name__ == '__main__':
    inst_dict = {'XHHG': '信合红谷接口查询', 'XH': '协和端口查询', 'WB': "外部接口查询"}
    # inst = 'XHHG'
    # inst = 'WB'
    inst = 'WB'
    print(f'@@@开始更新{inst}登录信息@@@')
    update_auth(inst)
    print('-----' * 10)
    time.sleep(5)
